#include <tinyhal.h>
#include "RGBLEDMatrix.h"
const unsigned char* Font_GetGlyph16(unsigned short u);

// D2 P06   pinCK
// D3 P05   pinXR
// D4 P39   pinXB
// D5 P3A   pinXG
// D6 P3C   pinR2
// D7 P08   pinR1
// D8 P3E   pinR0
// D9 P3B   pinEN

GPIO_PIN pinCK;
GPIO_PIN pinXR;
GPIO_PIN pinXG;
GPIO_PIN pinXB;
GPIO_PIN pinR0;
GPIO_PIN pinR1;
GPIO_PIN pinR2;
GPIO_PIN pinEN;
UINT8 cnt64;

#define PIN_L   0
#define PIN_H   1
#define WAIT_NL 0x6000

void RGBLM_Initialize(GPIO_PIN* pins)
{
	UINT8 i;
	pinCK = pins[0];
	pinXR = pins[1];
	pinXG = pins[2];
	pinXB = pins[3];
	pinR0 = pins[4];
	pinR1 = pins[5];
	pinR2 = pins[6];
	pinEN = pins[7];
	for (i = 0; i < 8; i++)
		CPU_GPIO_EnableOutputPin(pins[i], PIN_L);
    cnt64 = 0;
}

void RGBLM_SelectLine(UINT8 n)
{
    CPU_GPIO_SetPinState(pinR0, n & 1);
    CPU_GPIO_SetPinState(pinR1, n & 2);
    CPU_GPIO_SetPinState(pinR2, n & 4);

}

void RGBLM_TurnOn()
{
    CPU_GPIO_SetPinState(pinEN, PIN_H);
}

void RGBLM_TurnOff()
{
    CPU_GPIO_SetPinState(pinEN, PIN_L);
}

void RGBLM_UpdateCount()
{
    if (++(cnt64) >= 3)
        cnt64 = 0;
}

UINT8 RGBLM_GetColor8(UINT8 col64)
{
    UINT8 col8 = 0;
    if (cnt64 < ((col64 >> 0) & 3))
        col8 |= 1;
    if (cnt64 < ((col64 >> 2) & 3))
        col8 |= 2;
    if (cnt64 < ((col64 >> 4) & 3))
        col8 |= 4;
    return col8;
}

void RGBLM_DrawLine8(UINT8 pattern, UINT8 fcol, UINT8 bcol)
{
    UINT8 i;
    for (i = 0; i < 8; i++, pattern >>= 1) {
        if (pattern & 0x01) {
            CPU_GPIO_SetPinState(pinXR, !(fcol & 1));
            CPU_GPIO_SetPinState(pinXG, !(fcol & 2));
            CPU_GPIO_SetPinState(pinXB, !(fcol & 4));
        } else {
            CPU_GPIO_SetPinState(pinXR, !(bcol & 1));
            CPU_GPIO_SetPinState(pinXG, !(bcol & 2));
            CPU_GPIO_SetPinState(pinXB, !(bcol & 4));
         }
        CPU_GPIO_SetPinState(pinCK, PIN_H);
        CPU_GPIO_SetPinState(pinCK, PIN_L);
    }
}

void RGBLM_DrawLine64(UINT8 pattern, UINT8 fcol, UINT8 bcol)
{
    RGBLM_DrawLine8(pattern, RGBLM_GetColor8(fcol), RGBLM_GetColor8(bcol));
    RGBLM_UpdateCount();
}

void RGBLM_DrawPat(UINT8 pixels[8])
{
    UINT8 i;
    CPU_GPIO_SetPinState(pinCK, PIN_L);
    for (i = 0; i < 8; i++) {
        uint8_t col8 = RGBLM_GetColor8(*pixels++);
        CPU_GPIO_SetPinState(pinXR, !(col8 & 1));
        CPU_GPIO_SetPinState(pinXG, !(col8 & 2));
        CPU_GPIO_SetPinState(pinXB, !(col8 & 4));
        CPU_GPIO_SetPinState(pinCK, PIN_H);
        CPU_GPIO_SetPinState(pinCK, PIN_L);
    }
    RGBLM_UpdateCount();
}

void RGBLM_WaitLine(volatile uint32_t loop)
{
    RGBLM_TurnOn();
    while (loop-- > 0) ;
    RGBLM_TurnOff();
}

void RGBLM_Font(UINT8* font)
{
    uint8_t i = 0;
    uint8_t col = 0x07;
    for (i = 0; i < 8; i++) {
        RGBLM_SelectLine(i);
        RGBLM_DrawLine8(font[i], col, 0);
        RGBLM_WaitLine(WAIT_NL);
    }
}

void RGBLM_GetFontBitmap(UINT16 unicode, UINT8 *fb, UINT8 bytes)
{
	UINT8 *pfont;
	UINT32 i;

	if (unicode < 0x80) {
		pfont = Font_GetGlyph((unsigned char)unicode);
	} else {
		pfont = Font_GetGlyph16((unsigned short)unicode);
	}
	if (pfont != NULL) {
		memcpy((void *)fb, (const void *)pfont, (size_t)bytes);
	} else {
		memset((void *)fb, 0, (size_t)bytes);
	}
}
